import 'dart:convert';
import 'dart:io';

import 'package:aichat_flutter_wallet/kai_print.dart';
import 'package:aichat_flutter_wallet/module_common/mpc_help/chainListTool.dart';
import 'package:aichat_flutter_wallet/module_common/utils/util.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:lib_database/lib_database.dart';
import 'package:lib_util/lib_util.dart';
import 'package:lib_web3/lib_web3.dart';

import '../../../module_common/model/chain_lists_model.dart';
import '../../../module_common/network/chains_type/ethchain.dart';
import '../../../module_common/provider/token_list_provider.dart';

import '../../../module_common/provider/wallet_info_provider.dart';
import '../../../module_common/widgets/button/public_button.dart';
import '../../../module_common/widgets/header/page_header.dart';
import '../../../module_common/widgets/image/public_image.dart';
import '../../../module_common/widgets/loading/small_loading.dart';
import '../../../module_common/widgets/public_tip/public_tip.dart';
import '../../../module_common/widgets/public_tip/validate_tip.dart';
import '../widgets/sheet/customtoken_confirm_sheet.dart';

//添加自定义代币页
class WalletCustomToken extends StatefulWidget {
  const WalletCustomToken({Key? key}) : super(key: key);

  @override
  _WalletCustomTokenState createState() => _WalletCustomTokenState();
}

class _WalletCustomTokenState extends State<WalletCustomToken> {
  TextEditingController _contractController = TextEditingController();
  FocusNode _contractfocusNode = FocusNode();

  TextEditingController _symbolController = TextEditingController();
  FocusNode _symbolfocusNode = FocusNode();

  TextEditingController _decimalsController = TextEditingController();
  FocusNode _decimalsfocusNode = FocusNode();

  String _contractError = "";
  String _symbolError = "";
  String _decimalsError = "";

  ERC20Token? tokenItem;
  bool isLoading = false;
  bool isadding = false;

  @override
  void initState() {
    super.initState();

    _contractfocusNode.addListener(_handleFocusChange);

    //初始化
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      context.read<TokenListNotifier>().resetSearchText();
      initPopularTokensFromSP();
    });
  }

  void _handleFocusChange() async {
    if (!_contractfocusNode.hasFocus) {
      String value = _contractController.text;
      if (value.length <= 0) return;
      setState(() {
        _contractError = "";
      });

      // 查询代币 列表是否存在
      final customTokenList = context.read<TokenListNotifier>().tokenList;
      Token? result = customTokenList.firstWhereOrNull((element) {
        return element.contract == value;
      });
      if (result != null) {
        setState(() {
          _contractError = "Tokens added";
        });
        return;
      }
      String _symbolValue = _symbolController.text;
      String _decimalsValue = _decimalsController.text;
      if (tokenItem?.address == value && _decimalsValue.length > 0) {
        return;
      }
      if (isLoading) {
        return;
      }
      if (mounted)
        setState(() {
          isLoading = true;
        });
      try {
        //  判断 是否 合约
        var walletChain = context.read<WalletInfoNotifier>().walletChain;
        String rpc = ObjectBox()
            .nodeInfoModel
            .getSelectedNodeInfo(walletChain!.shortName)
            .url;
        final chainName = context.read<WalletInfoNotifier>().walletChain!.name;
        Map<String, dynamic>? result =
            await ChainListTool.getERC20TokenInfoByRpc(
                rpc: rpc, tokenAddress: value, symbol: chainName);
        if (result != null && result!.isEmpty) {
          final userAddress =
              context.read<WalletInfoNotifier>()
                  .walletAddress;
          setState(() {
            isLoading = false;
            _contractError =
                "The ${walletChain.shortName} chain did not find the token address associated with ${userAddress} .";
          });
          return;
        }
        if (result == null) {
          setState(() {
            isLoading = false;
            _contractError =
                "The token contract address is wrong. The changed address may not be the token address of ${walletChain.shortName}.";
          });
          return;
        }
        _decimalsController.text = result['decimals'].toString();
        _symbolController.text =
            _symbolValue.isNotEmpty ? _symbolValue : result['symbol'];
        var tokenName=result['name'] ?? result['symbol'];
        if([95279725].contains(result['chainId'])){
          tokenName=_symbolController.text ?? '';
        }
        tokenItem = new ERC20Token(
            result['chainId'],
            result['address'],
            result['decimals'],
            _symbolController.text ?? '',
            tokenName,
            result['isNative'],
            result['isToken'],
            '');
        if (mounted)
          setState(() {
            isLoading = false;
          });
      } catch (e) {
        print('e $e');
        if (mounted)
          setState(() {
            isLoading = false;
            _contractError =
                "Try switching to other RPC networks so you can get a better experience";
          });
        Log().e(e);
      }
    } else {
      print('Focus');
    }
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _contractfocusNode.removeListener(_handleFocusChange);
    _contractController.dispose();
    _contractfocusNode.dispose();
    _symbolController.dispose();
    _symbolfocusNode.dispose();
    _decimalsController.dispose();
    _decimalsfocusNode.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: PageHeaderCom(
        title: String.fromEnvironment('emailString',
            defaultValue: 'Custom Tokens'),
        showBottomBorder: false,
      ),
      body: SingleChildScrollView(
          // physics: NeverScrollableScrollPhysics(),
          child: Column(
        children: [
          SizedBox(height: 10.w),
          networkWidget(),
          SizedBox(height: 20.w),
          contractWidget(),
          // SizedBox(height: 20),
          // nameWidget(),
          SizedBox(height: 20.w),
          symbolWidget(),
          SizedBox(height: 20.w),
          decimalsWidget(), //到这里的底部为420
          SizedBox(
            height: MediaQuery.of(context).size.height -
                MediaQuery.of(context).padding.top - //状态栏
                44.w - //导航栏
                470.w - //总控件高度
                55.w - //按钮高度
                20.w, //底部安全区高度
          ),
        ],
      )),
      bottomNavigationBar: bottomControl(),
    );
  }

  Widget titleWidget(String title) {
    return Text(title,
        style: TextStyle(
            fontSize: 14.sp,
            fontWeight: FontWeight.w500,
            color: "#333333".toColor()));
  }

  Widget networkWidget() {
    return Padding(
        padding: EdgeInsets.fromLTRB(20.w, 3.w, 20.w, 3.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            titleWidget("Current network"),
            SizedBox(height: 10.w),
            Container(
              decoration: BoxDecoration(
                border: Border.all(color: "#E0E0E0".toColor()),
                borderRadius: BorderRadius.circular(10.0.w),
              ),
              height: 46.w,
              child: Row(
                children: [
                  SizedBox(width: 15.w),
                  ClipRRect(
                      borderRadius: BorderRadius.circular(30.w),
                      child: PublicImage(
                        image: context
                            .watch<WalletInfoNotifier>()
                            .walletChain!
                            .logo,
                        width: 30.w,
                        height: 30.w,
                      )),
                  SizedBox(width: 10.w),
                  titleWidget(
                      context.watch<WalletInfoNotifier>().walletChain!.name)
                ],
              ),
            )
          ],
        ));
  }

  Widget contractWidget() {
    return Padding(
        padding: EdgeInsets.fromLTRB(20.w, 3.w, 20.w, 3.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            titleWidget("Token Contract"),
            SizedBox(height: 10.w),
            Container(
              decoration: BoxDecoration(
                  color: Color.fromRGBO(246, 246, 246, 1),
                  borderRadius: BorderRadius.all(Radius.circular(10.w))),
              child: textInputControl(
                  inputFormatters: [
                    FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]")),
                    // 只允许输入英文大小写+数字
                    LengthLimitingTextInputFormatter(100)
                  ],
                  hintText: 'Please enter contract address',
                  maxLines: 2,
                  focusNode: _contractfocusNode,
                  controller: _contractController,
                  textInputAction: TextInputAction.next,
                  onEditingComplete: () {
                    //点击confirm
                    _contractfocusNode.nextFocus();
                    _handleFocusChange();
                  },
                  onChanged: (e) {
                    setState(() {
                      _contractError = "";
                      _symbolController.clear();
                      _decimalsController.clear();
                    });
                  }),
            ),
            Visibility(
                visible: !_contractError.isEmpty,
                child: ValidateTip(
                    text: _contractError,
                    margin: EdgeInsets.only(top: 10.w),
                    onClose: () {
                      setState(() {
                        _contractError = "";
                      });
                    })),
          ],
        ));
  }

  void handleSymbolChange(){
    String _symbolValue = _symbolController.text;
    if (tokenItem != null) {
      tokenItem!.symbol = _symbolValue;
      if([95279725].contains(tokenItem?.chainId)){
        tokenItem!.name =_symbolController.text ?? '';
      }
    }
    if (_symbolValue.length <= 0) {
      setState(() {
        _symbolError = "Token symbol cannot be empty";
      });
    } else {
      setState(() {
        _symbolError = "";
      });
    }
  }

  Widget symbolWidget() {
    return Padding(
        padding: EdgeInsets.fromLTRB(20.w, 3.w, 20.w, 3.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            titleWidget("Token Symbol"),
            SizedBox(height: 10.w),
            textInputControl(
                hasLoad: true,
                height: 46.w,
                inputFormatters: [
                  FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]")),
                  // 只允许输入英文大小写
                  LengthLimitingTextInputFormatter(20)
                ],
                onChanged: (value) {
                  handleSymbolChange();
                },
                hintText: 'Please enter the token symbol',
                focusNode: _symbolfocusNode,
                controller: _symbolController,
                textInputAction: TextInputAction.next,
                onTapOutside: (){
                  handleSymbolChange();
                },
                onEditingComplete: () {
                  //点击confirm
                  _symbolfocusNode.nextFocus();
                  handleSymbolChange();
                }),
            Visibility(
                visible: !_symbolError.isEmpty,
                child: ValidateTip(
                    text: _symbolError,
                    margin: EdgeInsets.only(top: 10.w),
                    onClose: () {
                      setState(() {
                        _symbolError = "";
                      });
                    }))
          ],
        ));
  }

  Widget decimalsWidget() {
    return Padding(
        padding: EdgeInsets.fromLTRB(20.w, 3.w, 20.w, 3.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            titleWidget("Token Decimals"),
            SizedBox(height: 10.w),
            textInputControl(
              donTShow: true,
              hasLoad: true,
              height: 46.w,
              isDisabled: true,
              inputFormatters: [
                FilteringTextInputFormatter.allow(RegExp("[0-9 ]"))
              ],
              // 只允许输入数字
              hintText: '0',
              focusNode: _decimalsfocusNode,
              controller: _decimalsController,
              textInputAction: TextInputAction.done,
              onEditingComplete: () {
                //点击confirm
                _decimalsfocusNode.unfocus();
              },
            ),
            Visibility(
                visible: !_decimalsError.isEmpty,
                child: ValidateTip(
                    text: _decimalsError,
                    margin: EdgeInsets.only(top: 10.w),
                    onClose: () {
                      setState(() {
                        _decimalsError = "";
                      });
                    })),
          ],
        ));
  }

  Widget textInputControl(
      {double? height,
      bool donTShow = false,
      List<TextInputFormatter>? inputFormatters,
      int? maxLines = 1,
      String hintText = '',
      FocusNode? focusNode,
      TextEditingController? controller,
      TextInputAction? textInputAction,
      bool isDisabled = false,
      void Function()? onEditingComplete,
      void Function(String)? onChanged,
      void Function()? onTapOutside,
      bool hasLoad = false}) {
    return Container(
      height: height,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8.w),
        color: Color.fromRGBO(246, 246, 246, 1),
      ),
      child: Stack(
        children: [
          Row(
            children: [
              Expanded(
                child: TextField(
                    cursorHeight: 20.w,
                    readOnly: isDisabled,
                    textInputAction: textInputAction,
                    inputFormatters: inputFormatters,
                    textAlign: TextAlign.start,
                    textAlignVertical: TextAlignVertical.top,
                    controller: controller,
                    focusNode: focusNode,
                    onTapOutside: (PointDownEvent) {
                      focusNode?.unfocus();
                      if (onTapOutside != null) onTapOutside();
                    },
                    onEditingComplete: onEditingComplete,
                    onChanged: onChanged,
                    maxLines: maxLines,
                    style: TextStyle(
                        color: Color.fromRGBO(51, 51, 51, 1),
                        fontWeight: FontWeight.w400,
                        fontSize: 14.sp,
                        height: 20.w / 14.w),
                    decoration: InputDecoration(
                      contentPadding: EdgeInsets.all(15.w),
                      border: InputBorder.none,
                      hintText: hintText,
                      hintStyle: TextStyle(
                        fontSize: 14.sp,
                        color: "#BEBDCA".toColor(),
                      ),
                    )),
              ),
              Container(
                width: 55.w,
                alignment: Alignment.centerRight,
                child: Visibility(
                    visible: donTShow
                        ? false
                        : (controller!.text.isNotEmpty && !isLoading),
                    child: GestureDetector(
                      onTap: () {
                        setState(() {
                          if (!hasLoad) {
                            _symbolController.clear();
                            _decimalsController.clear();
                          }
                          controller?.clear();
                        });
                      },
                      child: Padding(
                        padding: EdgeInsets.only(left: 20.w, right: 15.w),
                        child: Image.asset(
                          'assets/images/common/clear-input.png',
                          width: 16.w,
                          height: 16.w,
                        ),
                      ),
                    )),
              ),
              Visibility(
                visible: isLoading && hasLoad,
                child: Container(
                  width: 35.w,
                  padding: EdgeInsets.only(right: 15.w),
                  child: SmallLoading(
                    width: 20.w,
                    height: 20.w,
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget bottomControl() {
    return Container(
      margin: EdgeInsets.only(bottom: Platform.isIOS ? 49.w : 10.w),
      child: PublicButton(
          disabledStatus: !(_contractController.text.isNotEmpty &&
              _symbolController.text.isNotEmpty &&
              _decimalsController.text.isNotEmpty),
          type: ButtonType.private,
          text: 'Confirm',
          onClick: () {
            if (_contractController.text.isEmpty ||
                _symbolController.text.isEmpty ||
                _decimalsController.text.isEmpty) return;
            if (_contractError.isEmpty &&
                _decimalsError.isEmpty &&
                _symbolError.isEmpty) {
              Utils.showBottomSheetDialog(
                  context,
                  CustomTokenConfirmSheet(
                      tokenItem: tokenItem!.toJson(),
                      onConfirm: () async {
                        try {
                          print('tokenItem ${tokenItem!.toJson()}');
                          if (isadding) return;
                          isadding = true;
                          //检查objbox
                          Token? isExist = ObjectBox()
                              .tokenModel
                              .getTokenByWalletInfoIdAndTokenContract(
                                  context
                                      .read<TokenListNotifier>()
                                      .walletInfoId,
                                  tokenItem!.address.toString());

                          if (isExist != null) {
                            isadding = false;
                            Toast.show(context,
                                status: '2',
                                position: Dpositon.center,
                                duration: Duration(milliseconds: 2500),
                                message: 'The token address already exists');
                            return;
                          }


                          //查sp
                          var isSPExist = popularTokens.firstWhereOrNull(
                              (element) =>
                                  element.contract ==
                                  tokenItem!.address.toString());

                          if (isSPExist != null) {
                            isadding = false;
                            Toast.show(context,
                                status: '2',
                                position: Dpositon.center,
                                duration: Duration(milliseconds: 2500),
                                message: 'The token address already exists');
                            return;
                          }

                          Token item = Token(
                              walletInfoId: context
                                  .read<TokenListNotifier>()
                                  .walletInfoId,
                              contractType: TokenType.token20.name,
                              contract: tokenItem!.address.toString(),
                              name: tokenItem!.name.toString(),
                              symbol: tokenItem!.symbol.toString(),
                              decimals: tokenItem!.decimals!,
                              balance: '0.00',
                              valueusd: '0.00',
                              change24h: '0.00',
                              enable: true,
                              isAdded: true,
                              isCustom: true);
                          await context
                              .read<TokenListNotifier>()
                              .addCustomTokens(item);
                          Navigator.of(context).pop();
                          Toast.show(context,
                                  status: '1',
                                  message: 'Operating succeeded',
                                  position: Dpositon.bottom,
                                  duration: Duration(milliseconds: 2500))
                              .then((value) {
                            isadding = true;
                            Navigator.of(context).pop();
                          });
                          isadding = false;
                        } catch (e) {
                          isadding = false;
                          Log().e(e);
                        }
                      })).then((value) {
                isadding = false;
              });
            }
          }),
    );
  }

  List<Token> popularTokens = [];
  //每次进入页面的时候从SP拿数据初始化
  void initPopularTokensFromSP() {
    List<dynamic> list = SP().getKeyTokenList();
    //拿到已添加的代币地址
    var addedList = context
        .read<TokenListNotifier>()
        .tokenFungibleList
        .map((e) => e.contract);

    //当前chainID
    var chainID = context
        .read<WalletInfoNotifier>()
        .walletInfo!
        .getChain()!
        .evmInfo!
        .chainId;

    list.forEach((jsonString) {
      var json = jsonDecode(jsonString);
      var tokenObj = TokensObjModel.fromJson(json);
      //提出不同chainID的token
      if (chainID.toString() != tokenObj.chain_id) {
        return;
      }
      //网络Token类型，转本地数据库的Token
      Token token = Token(
        walletInfoId: context.read<TokenListNotifier>().walletInfoId,
        contractType: TokenType.token20.name,
        contract: tokenObj.contract_address,
        name: tokenObj.name.toString(),
        symbol: tokenObj.symbol.toString(),
        logo: tokenObj.icon,
        decimals: int.parse(tokenObj.decimal),
        balance: '0.00',
        valueusd: '0.00',
        change24h: '0.00',
        enable: true,
        isAdded: addedList.contains(tokenObj.contract_address),
      );

      popularTokens.add(token);
    });
  }
}
